#ifndef webhttpd__HttpResponse
#define webhttpd__HttpResponse

#include <glib.h>
#include <srclink/utils.h>

typedef struct HttpResponseBody {
    char *content;
    size_t size;
} HttpResponseBody;

typedef struct HttpResponse {
    int status_code;
    GHashTable *headers;
    HttpResponseBody body;
} HttpResponse;

typedef struct HttpResponseRaw {
    char *content;
    size_t size;
} HttpResponseRaw;

static inline const char* get_reason_phrase(int status_code);

static inline HttpResponseRaw *parse_response(const HttpResponse *response) {
    // 检查传入的 response 是否为空
    if (response == NULL) {
        return NULL;
    }

    HttpResponseRaw *response_raw = malloc(sizeof(HttpResponseRaw));
    if (!response_raw) {
        return NULL; // 内存分配失败，返回 NULL
    }

    // 准备响应状态行
    char status_line[BUFFER_SIZE];
    const char *status_message = get_reason_phrase(response->status_code);

    // 格式化状态行
    snprintf(status_line, BUFFER_SIZE, "HTTP/1.1 %d %s\r\n", response->status_code, status_message);

    // 计算状态行的长度
    size_t status_line_len = strlen(status_line);

    // 添加长度请求头
    char content_size_str[100];
    snprintf(content_size_str, 100, "%lld", response->body.size);
    g_hash_table_insert(response->headers, g_strdup("Content-Length"), g_strdup(content_size_str));

    // 计算请求头的长度
    size_t headers_len = 0;
    GList *keys = g_hash_table_get_keys(response->headers);

    for (GList *key = keys; key != NULL; key = key->next) {
        char *header_key = (char *) key->data;
        char *header_value = (char *) g_hash_table_lookup(response->headers, header_key);

        if (header_key == NULL || header_value == NULL) {
            g_list_free(keys);
            free(response_raw);
            return NULL; // 如果头部有 NULL 键或值，返回 NULL
        }

        headers_len += strlen(header_key) + strlen(header_value) + 4; // header: value\r\n
    }
    g_list_free(keys);

    // 请求体大小
    size_t body_len = response->body.size;

    // 计算总大小: 状态行 + 请求头 + 空行 + 请求体
    response_raw->size = status_line_len + headers_len + 2 + body_len; // 2 is for "\r\n" empty line
    response_raw->content = malloc(response_raw->size);

    if (!response_raw->content) {
        free(response_raw);
        return NULL; // 内存分配失败，返回 NULL
    }

    // 填充响应内容
    char *cursor = response_raw->content;

    // 1. 写入状态行
    memcpy(cursor, status_line, status_line_len);
    cursor += status_line_len;

    // 2. 写入请求头部
    keys = g_hash_table_get_keys(response->headers);
    for (GList *key = keys; key != NULL; key = key->next) {
        char *header_key = (char *) key->data;
        char *header_value = (char *) g_hash_table_lookup(response->headers, header_key);

        snprintf(cursor, BUFFER_SIZE, "%s: %s\r\n", header_key, header_value);
        cursor += strlen(cursor); // 更新游标位置
    }
    g_list_free(keys);

    // 3. 添加空行 (\r\n)
    memcpy(cursor, "\r\n", 2);
    cursor += 2;

    // 4. 写入请求体内容
    if (body_len > 0) {
        memcpy(cursor, response->body.content, body_len);
    }

    return response_raw;
}

// 获取状态码对应的原因短语
static inline const char* get_reason_phrase(int status_code) {
    switch (status_code) {
        case 100: return "Continue";
        case 101: return "Switching Protocols";
        case 102: return "Processing";
        case 200: return "OK";
        case 201: return "Created";
        case 202: return "Accepted";
        case 203: return "Non-Authoritative Information";
        case 204: return "No Content";
        case 205: return "Reset Content";
        case 206: return "Partial Content";
        case 207: return "Multi-Status";
        case 208: return "Already Reported";
        case 226: return "IM Used";
        case 300: return "Multiple Choices";
        case 301: return "Moved Permanently";
        case 302: return "Found";
        case 303: return "See Other";
        case 304: return "Not Modified";
        case 305: return "Use Proxy";
        case 307: return "Temporary Redirect";
        case 308: return "Permanent Redirect";
        case 400: return "Bad Request";
        case 401: return "Unauthorized";
        case 402: return "Payment Required";
        case 403: return "Forbidden";
        case 404: return "Not Found";
        case 405: return "Method Not Allowed";
        case 406: return "Not Acceptable";
        case 407: return "Proxy Authentication Required";
        case 408: return "Request Timeout";
        case 409: return "Conflict";
        case 410: return "Gone";
        case 411: return "Length Required";
        case 412: return "Precondition Failed";
        case 413: return "Payload Too Large";
        case 414: return "URI Too Long";
        case 415: return "Unsupported Media Type";
        case 416: return "Range Not Satisfiable";
        case 417: return "Expectation Failed";
        case 418: return "I'm a teapot";
        case 421: return "Misdirected Request";
        case 422: return "Unprocessable Entity";
        case 423: return "Locked";
        case 424: return "Failed Dependency";
        case 426: return "Upgrade Required";
        case 428: return "Precondition Required";
        case 429: return "Too Many Requests";
        case 431: return "Request Header Fields Too Large";
        case 451: return "Unavailable For Legal Reasons";
        case 500: return "Internal Server Error";
        case 501: return "Not Implemented";
        case 502: return "Bad Gateway";
        case 503: return "Service Unavailable";
        case 504: return "Gateway Timeout";
        case 505: return "HTTP Version Not Supported";
        case 506: return "Variant Also Negotiates";
        case 507: return "Insufficient Storage";
        case 508: return "Loop Detected";
        case 510: return "Not Extended";
        case 511: return "Network Authentication Required";
        default:  return "Unknown Status";
    }
}

#endif
